package com.apes.scm.masterdata.party.service;

import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Filter;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.scm.masterdata.party.model.Party;
import com.apes.scm.masterdata.party.model.PartyIdentification;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.model.RoleType;
import com.apes.scm.masterdata.party.repository.*;
import com.mongodb.client.model.Filters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * 功能：当事人服务
 *
 * @author xul
 * @create 2018-01-23 14:35
 */
@Service("partyService")
public class PartyService extends DomainService {

    @Autowired
    PartyRepository partyRepository;
    @Autowired
    public PartyIdentificationRepository partyIdentificationRepository;
    @Autowired
    public SequenceService sequenceService;

    @Autowired
    PartyRoleRepository partyRoleRepository;


    /*
     *  party : party 信息
     *  partyRoleType: 角色类型   Company: 公司， Supplier： 供应商，Customer： 客户(单位/个人)， Employee: 员工
     *  partyRoleCode 角色编码 自定义编码 或者为空
     * */
    public Party saveAndFlush(Party party, String partyRoleType,String partyRoleCode) {
        //初始化 partyRoles 对象
        Set<PartyRole> partyRoles = party.getPartyRoles();
        if (partyRoles == null){
            partyRoles = new HashSet();
            party.setPartyRoles(partyRoles);
        }
        //初始化 partyIdentifications 对象
        Set<PartyIdentification> partyIdentifications = party.getPartyIdentifications();
        if (partyIdentifications == null){
            partyIdentifications = new HashSet();
            party.setPartyIdentifications(partyIdentifications);
        }
        //检查Roles状态，如果是创建操作，则对Code进行编码操作
        String code = partyRoleCode;
        for(PartyRole partyRole: partyRoles){
            // 为空，代表系统默认编码
            if (partyRole.getId()==null){
                partyRole.setParty(party);
                RoleType roleType = new RoleType();
                roleType.setId(partyRoleType);
                partyRole.setRole(roleType);
                // 获取角色对应编码
                code = sequenceService.getId("PARTY_" + partyRoleType);
                partyRole.setId(code);
            }
        }
        // 编码更新时没传编码进来或者创建取不到编码
        if( code == null) {
            throw new RuntimeException("定义角色编码不允许为空，请检查！");
        }

        operatorProcess(party); // 运营商处理

//        boolean haveUscc = false;
//        boolean haveCode = false;
//        boolean haveMobile = false;
//        for (PartyIdentification partyIdentification: partyIdentifications){
//            //如果有标识符则更新它
//            if (partyIdentification.getPartyIdType().equals("PIT_USCC")){
//                partyIdentification.setIdValue(party.getCorporate().getUscc());
//                haveUscc = true;
//            }
//            if (partyIdentification.getPartyIdType().equals("PIT_mobile")){
//                partyIdentification.setIdValue(party.getPerson().getMobileNumber());
//                haveMobile = true;
//            }
//            if (partyIdentification.getPartyIdType().equals(partyRoleType + "Code")){
//                partyIdentification.setIdValue(code);
//                haveCode = true;
//            }
//        }
//        //如果没有标识符则创建
//        if (party.getPartyType().equals("corporate")){  // 法人单位: 公司，供应商等
//            if(!haveUscc &&party.getCorporate()!=null&& party.getCorporate().getUscc() != null){
//                PartyIdentification partyIdentification = new PartyIdentification();
//                partyIdentification.setParty(party);
//                if (!partyRoleType.equals("Supplier")&&!partyRoleType.equals("Customer")) {
//                    partyIdentification.setPartyIdType("PIT_USCC");
//                    partyIdentification.setIdValue(party.getCorporate().getUscc());
//                    partyIdentifications.add(partyIdentification);
//                }
//            }
//        }else{  // 个人 : 会员， 员工 等
//            if(!haveMobile && party.getPerson() != null &&party.getPerson().getMobileNumber() != null){
//                PartyIdentification partyIdentification = new PartyIdentification();
//                partyIdentification.setParty(party);
//                partyIdentification.setPartyIdType("PIT_mobile");
//                partyIdentification.setIdValue(party.getPerson().getMobileNumber());
//                partyIdentifications.add(partyIdentification);
//            }
//        }
//
//        if(!haveCode){
//            PartyIdentification partyIdentification;
//            partyIdentification = new PartyIdentification();
//            partyIdentification.setParty(party);
//            partyIdentification.setPartyIdType(partyRoleType + "Code");
//            partyIdentification.setIdValue(code);
//            partyIdentifications.add(partyIdentification);
//        }
        return partyRepository.saveAndFlush(party);
    }


    /*
     *  定义界面（弹窗）
     *  角色编码可能用同一个，比如单位客户 和 个人客户 都为 Customer
     *  partyType为 person 为个人角色， corporate 为单位角色
     * */
    public Page<Party> findPartyAllByTypeAndRole(SimpleRequest request, String partyType, String roleTypeId) {
        JSONObject requestObj = request.getJO();
        List<Map> filters = new ArrayList<Map>();
        if(requestObj.get("condition") != null) {
            filters = request.get("condition");
        }else {
            Map filter = new HashMap();
            String id = requestObj.getString("key");
            try {
                Integer.parseInt(id);
                filter.put("field","partyRoles.id");
            }catch (NumberFormatException e){
                filter.put("field","name");
            }
            filter.put("operator","LIKE");
            filter.put("value",id);
            filters.add(filter);
        }
        // 当事人类型
        Map typeParams = new HashMap<>();
        typeParams.put("field","partyType");
        typeParams.put("operator","EQ");
        typeParams.put("value",partyType);
        filters.add(typeParams);
        // 角色类型
        Map roleParams = new HashMap<>();
        roleParams.put("field","partyRoles.role");
        roleParams.put("operator","EQ");
        RoleType roleType = new RoleType();
        roleType.setId(roleTypeId);
        roleParams.put("value",roleType);
        filters.add(roleParams);
        Sort sort = new Sort(Sort.Direction.ASC, "partyRoles.id");
        return partyRepository.findAll( JpaDsl.toCriteria(filters),PageRequest.of(request.get("page"), request.get("size")));
    }

    /*
     * 通过角色类型查找角色编码
     * 适用于 Party 不是主体, 作为主体ManyToOne等关联适用
     * */
    public String findRoleCodeByRole(Party party, String role){
        return Optional.ofNullable(party).map(p -> partyRoleRepository.findByPartyIdAndRoleId(party.getId(), role)).map(PartyRole::getId).orElse(null);
    }

    /**
     * Party类 findAll 插件 结果格式化
     * 添加公司编码、人员编码等
     */
    public Page<Party> findAllFormat(SimpleRequest request) {
        Page<Party> partyPage = request.getO(Page.class);
        partyPage.getContent().forEach(this::roleCodeFormat);
        return partyPage;
    }

    /**
     * Party类 findOne 插件 结果格式化
     * 添加公司编码、人员编码等
     */
    public Party findOneFormat(SimpleRequest request) {
        Party party = partyRepository.findOne(Long.valueOf(request.get("id")));
        roleCodeFormat(party);
        return party;
    }


    /*
     * Party 赋值 roleCode
     * */
    public void roleCodeFormat(Party party) {
        Optional.ofNullable(party).map(Party::getPartyRoles).ifPresent(
                (partyRoles) -> {
                    partyRoles.forEach(
                            (partyRole) -> {
                                String roleId = partyRole.getRole().getId();
                                if("Company".equals(roleId)) {
                                    party.setCompanyCode(partyRole.getId());
                                    party.setAccessProvider(SpringManager.getBean(AccessProviderRepository.class).findByCompany(party.getPatyRoleByType("Company").getId()));
                                }else if("Customer".equals(roleId)) {
                                    party.setCustomerCode(partyRole.getId());
                                }else if("Employee".equals(roleId)) {
                                    party.setPersonCode(partyRole.getId());
                                }else if("Supplier".equals(roleId)) {
                                    party.setSupplierCode(partyRole.getId());
                                }
                            }
                    );
                }
        );

    }



    /*
     * */
    public Party findOne(Long id) {
        return partyRepository.findOne(id);
    }

    /**
     * 根据SUCC角色信息
     *
     * @param request
     * @return
     */
    public Party findPartyBySUCC(SimpleRequest request) {
        String code = request.get("uscc");
        Party party= findPartyByIdTypeAndIdValue("PIT_USCC",code);
        roleCodeFormat(party);
        return party;
    }

    /**
     * 根据手机号码查找人员信息
     *
     * @param request
     * @return
     */
    public Party findByMobile(SimpleRequest request) {
        String code = request.getO(String.class);
        PartyIdentification identification = partyIdentificationRepository.findFirstByPartyIdTypeAndIdValue("PIT_mobile", code);
        return identification.getParty();
    }

    /**
     * 根据手机号码查找人员信息
     *
     * @param request
     * @return
     */
    public Party findByMobile2(SimpleRequest request) {
        String code = request.get("mobile");
        PartyIdentification identification = partyIdentificationRepository.findFirstByPartyIdTypeAndIdValue("PIT_mobile", code);
        if(identification!=null){
            return identification.getParty();
        } else {
            return null;
        }

    }

    /**
     *
     * @param request
     * @return
     */
    public Party findByCode(SimpleRequest request, String sRoleType) {
        String code = request.getO(String.class);
        PartyIdentification identification = partyIdentificationRepository.findFirstByPartyIdTypeAndIdValue(sRoleType, code);
        return identification.getParty();
    }


    // 根据标识编码跟类型查询角色信息
    public Party findPartyByIdTypeAndIdValue(String idType, String idValue) {
        PartyIdentification identification = partyIdentificationRepository.findFirstByPartyIdTypeAndIdValue(idType, idValue);
        if (identification != null) {
            return identification.getParty();
        }
        return  null;
    }

    // 根据标识编码、标识类型 查某个类型的角色信息
    public Party findPartyByIdTypeAndIdValueAndRoleId(String idType, String idValue, String roleId) {
        Party party = findPartyByIdTypeAndIdValue(idType,idValue );
        if( party != null) {
            boolean isRole = party.isRole(roleId);
            if( !isRole ) { // 不是该类型返回null
                return null;
            }
        }
        return party;
    }

    /**
     * 人员界面下拉所属公司
     * @param request
     * @return
     */
    public Page<Party> findCompany(SimpleRequest request) {
        long idKey = 999999999;
        String nameKey = request.get("key");
        try {
            idKey = Long.parseLong(request.get("key"));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return partyRepository.findCompany(idKey, nameKey, PageRequest.of(request.get("page"), request.get("size")));
    }

    /**
     * 查找角色信息
     * @param request
     * @return
     */
    public Party findPartyByRoleId(SimpleRequest request) {
        try {
            JSONObject jo = request.getJO();
            return partyRoleRepository.findOne(jo.getString("id")).getParty();
        } catch (Exception e) {
            return null;
        }
    }


    public Page<Party> findAllSupplier(SimpleRequest request, String partyType, String roleTypeId) {
        Group group = request.getO(Group.class);
        List<Filter> filters = new ArrayList();
        // 当事人类型
        Filter typeParams = new Filter();
        typeParams.setField("partyType");
        typeParams.setOperator("EQ");
        typeParams.setValue(partyType);
        filters.add(typeParams);
        // 角色类型
        Filter roleParams = new Filter();
        roleParams.setField("partyRoles.role");
        roleParams.setOperator("EQ");
        RoleType roleType = new RoleType();
        roleType.setId(roleTypeId);
        roleParams.setValue(roleType);
        filters.add(roleParams);
        group.setFilters(filters);
        Page<Party> partyPage = partyRepository.findAll(JpaDsl.build(group, true), PageRequest.of(request.get("page"), request.get("size")));
        for (Party party : partyPage.getContent()) {
            roleCodeFormat(party);
        }
        return partyPage;
    }

    public void operatorProcess(Party party){
        // 运营商标记为true时，所属运营商要为空控制
        if (party.isOperatorSign() && !Objects.isNull(party.getBelongOperator())) throw new RuntimeException("运营商不能有所属运营商!");
        if (party.isOperatorSign()) {
            // 若运营商标记为true，则判断是否存在对应的运营商，否则生成
            long partyId = party.getId();
            PartyRole partyRole = null;
            if (partyId != 0) {
                partyRole = partyRoleRepository.findAll(JpaDsl.toCriteriaByEq("party.id",partyId,"role.id","Operator")).stream().findFirst().orElse(null);
            }
            if (partyRole != null) return;
            partyRole = new PartyRole();
            partyRole.setParty(party);
            RoleType roleType = new RoleType();
            roleType.setId("Operator");
            partyRole.setRole(roleType);
            String code = sequenceService.getId("PARTY_" + roleType.getId());
            partyRole.setId(code);
            party.getPartyRoles().add(partyRole);
        } else {
            // 若运营商标记为false，则判断是否存在对应的运营商，是则提示无法修改
            long partyId = party.getId();
            List<PartyRole> partyRoles = new ArrayList<>();
            if (!Objects.isNull(partyId)) {
                partyRoles = partyRoleRepository.findAll(JpaDsl.toCriteriaByEq("party.id", partyId,"role.id","Operator"));
            }
            if (!partyRoles.isEmpty()) throw new RuntimeException("已生成运营商，无法修改！");
//            partyRoles.stream().forEach(partyRole -> {
//                Set<PartyRole> partyRoleTemp = party.getPartyRoles().stream().filter(oldPartyRole -> {
//                    return !partyRole.getId().equals(oldPartyRole.getId());
//                }).collect(Collectors.toSet());
//                party.setPartyRoles(partyRoleTemp);
//            });
        }
    }
}
